﻿package com.winglish.as3.loader
{
	import flash.events.EventDispatcher;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.net.URLRequest;
	import flash.media.Sound;
	import flash.external.ExternalInterface;
	
	public class SoundLoader extends EventDispatcher
	{
		private var sound: Sound;
		private var soundURL: String;
		private var request: URLRequest;
		private var isLoading: Boolean;
		private var isReady: Boolean;
		
		public function SoundLoader( url: String = null )
		{
			super();
			soundURL = url;
			init();
		}
		
		/**
		 * 생성자에 url이 있으면 로드.
		 */
		private function init(): void
		{
			if( soundURL ) load( soundURL );
		}
		
		/**
		 * 사운드 로드.
		 * @param	url
		 */
		public function load( url: String = null ): void
		{
			if ( url ) request = new URLRequest( url );
			sound = new Sound();
			isLoading = true;
			addEvent( true );
			try
			{
				sound.load( request );
			}catch( e: Error )
			{
				trace( "......" );
			}
		}
		
		/**
		 * -
		 */
		public function close(): void
		{
			if( isLoading && !isReady )
			{
				isLoading = false;
				addEvent( false );
				sound.close();
				sound = new Sound();
			}
		}
		
		/**
		 * 클래스 
		 */
		public function destroy(): void
		{
			close();
			addEvent( false );
			sound = null;
			request = null;
		}
		
		/**
		 * 사운드
		 * @return
		 */
		public function getResult(): Sound
		{
			return sound;
		}
		
		/**
		 * 사운드 이벤트 등록
		 * @param	isEvent
		 */
		private function addEvent( isEvent: Boolean = true ): void
		{
			var listener: String = ( isEvent ) ? "addEventListener" : "removeEventListener";
			sound[ listener ]( Event.OPEN, onOpenHandler );
			sound[ listener ]( ProgressEvent.PROGRESS, onProgressHandler );
			sound[ listener ]( IOErrorEvent.IO_ERROR, onIoErrorHnadler );
			sound[ listener ]( Event.COMPLETE, onCompleteHandler );
		}
		
		/**
		 * 사운드 로드 시작할 때 이벤트.
		 * @param	e
		 */
		private function onOpenHandler( e: Event ): void
		{
			dispatchEvent( new Event( Event.OPEN ) );
		}
		
		/**
		 * 사운드 로드 진행 이벤트.
		 * @param	e
		 */
		private function onProgressHandler( e: ProgressEvent ): void
		{
			dispatchEvent( new ProgressEvent( ProgressEvent.PROGRESS, false, false, e.bytesLoaded, e.bytesTotal ) );
		}
		
		/**
		 * 사운드 로드 작업을 실패하게 만드는 입력/출력 오류 발생 이벤트.
		 * @param	e
		 */
		private function onIoErrorHnadler( e: IOErrorEvent ): void
		{
			var file:String = e.text.split("URL: ")[1];
			try {
				ExternalInterface.call("alert", soundURL + " : 파일이 없습니다.");
			}catch (e1:Error) {
				//throw new Error( file + " : 파일이 없습니다.");
				trace(file + " : 파일이 없습니다.");
			}
			dispatchEvent( new IOErrorEvent( IOErrorEvent.IO_ERROR ) );
		}

		/**
		 * 사운드 로드 완료 이벤트.
		 * @param	e
		 */
		private function onCompleteHandler( e: Event ): void
		{
			isReady = true;
			addEvent( false );
			dispatchEvent( new Event( Event.COMPLETE ) );
		}
		
		/**
		 * dispatchEvent
		 * @param	e
		 * @return
		 */
		override public function dispatchEvent( e: Event ): Boolean
		{
			if ( hasEventListener( e.type ) || e.bubbles ) return super.dispatchEvent( e );
			return true;
		}
	}
}